<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { message } from 'ant-design-vue';
import { useRoute, useRouter } from 'vue-router';
import {
  ApiOutlined,
  BranchesOutlined,
  CodeOutlined,
  DatabaseOutlined,
  DeleteOutlined,
  ExportOutlined,
  ImportOutlined,
  PlayCircleOutlined,
  ReloadOutlined,
  SaveOutlined,
  SettingOutlined,
  SwapOutlined,
  SyncOutlined
} from '@ant-design/icons-vue';
// 移除了Draggable导入，因为不再使用列表视图

import {
  executeStepByStep as apiExecuteStepByStep,
  continueStep,
  executeComputeFlow,
  fetchApiDefinitionById,
  fetchApiDefinitions,
  saveApiDefinition
} from '@/service/api/compute';
import { fetchParametersByModelIdReflection, listDiscoveredModels } from '@/service/api/valuation';
import CodeEditor from '@/components/custom/CodeEditor.vue';
import FlowChart from './components/FlowChart.vue';

// 响应式数据
const selectedApiId = ref<string | null>(null);
const apiDefinitions = ref<Api.Compute.ApiDefinition[]>([]);
const flowSteps = ref<Api.Compute.Step[]>([]);
const saving = ref(false);
const testing = ref(false);
const testModalVisible = ref(false);
const stepModalVisible = ref(false);
const stepByStepModalVisible = ref(false);
const testInput = ref('');
const testResult = ref<any>(null);
const stepByStepTesting = ref(false);
const stepByStepInput = ref('');
const stepByStepResult = ref<any>(null);
const currentStepIndex = ref(0);
// 移除了列表视图，仅保留流程图视图
const stepByStepContext = ref<any>(null);
const stepTestResults = ref<Record<number, any>>({});
const stepTestResultModalVisible = ref(false);
const currentViewingStepResult = ref<any>(null);
const currentViewingStepIndex = ref(-1);
// 流程图修改状态
const hasUnsavedChanges = ref(false);
const autoConnect = ref(false);
// 流程图连线信息
const flowConnections = ref<any[]>([]);
// 流程图节点位置信息
const nodePositions = ref<Record<string, { x: number; y: number }>>({});

// 模型相关的响应式数据
const availableModels = ref<any[]>([]);
const modelParameters = ref<any[]>([]);
const loadingModels = ref(false);

// 获取当前选中的API信息
const selectedApi = computed(() => {
  if (!selectedApiId.value) return null;
  return apiDefinitions.value.find(api => api.id === selectedApiId.value);
});
const editingStepIndex = ref(-1);
const testingStepIndex = ref(-1);
const currentStep = ref<Api.Compute.Step>({
  name: '',
  type: 'groovy',
  description: '',
  script: '',
  mappingConfig: '',
  url: '',
  method: 'GET',
  headers: '',
  query: '',
  dataSource: 'default'
});

// 方法
const loadApiDefinitions = async () => {
  try {
    const response = await fetchApiDefinitions();
    apiDefinitions.value = response || [];
  } catch {
    message.error('加载接口定义失败');
  }
};

const loadApiDefinition = async (apiId: string) => {
  try {
    const data = await fetchApiDefinitionById(apiId);

    if (data && data.flowDefinition) {
      try {
        // console.log('原始流程定义:', data.flowDefinition);

        // 尝试修复JSON中的转义问题
        let fixedJson = data.flowDefinition;

        // 先尝试直接解析，如果失败再进行修复
        try {
          JSON.parse(fixedJson);
        } catch {
          // console.log('初始解析失败，开始修复JSON:', parseError);

          // 更彻底的JSON修复策略
          // 1. 找到所有script字段并重新构建
          const scriptRegex = /"script":\s*"([^"]*(?:\\.[^"]*)*)"/g;
          fixedJson = fixedJson.replace(scriptRegex, (_match, scriptContent) => {
            // 对script内容进行彻底的转义处理
            const cleanScript = scriptContent
              // 先处理已有的转义字符
              .replace(/\\\\/g, '\\') // 处理双重转义的反斜杠
              .replace(/\\"/g, '"') // 处理转义的双引号
              // 然后重新转义所有需要转义的字符
              .replace(/\\/g, '\\\\') // 转义反斜杠
              .replace(/"/g, '\\"') // 转义双引号
              .replace(/'/g, "\\'")
              .replace(/\n/g, '\\n') // 转义换行符
              .replace(/\r/g, '\\r') // 转义回车符
              .replace(/\t/g, '\\t'); // 转义制表符

            return `"script": "${cleanScript}"`;
          });

          // console.log('修复后的JSON:', fixedJson);
        }

        // 修复mappingConfig中的JSON转义问题
        // 针对具体的JSON格式进行修复
        fixedJson = fixedJson.replace(
          /"mappingConfig":\s*"\{"user":\s*"\$\.result\[0\]"\}"/g,
          '"mappingConfig": "{\\"user\\": \\"$.result[0]\\"}"'
        );

        // 通用的mappingConfig修复
        fixedJson = fixedJson.replace(
          /"mappingConfig":\s*"\{"([^"]+)":\s*"([^"]+)"\}"/g,
          '"mappingConfig": "{\\"$1\\": \\"$2\\"}"'
        );

        console.log('修复后的JSON:', fixedJson);

        const flowDef = JSON.parse(fixedJson) as any;
        // console.log('解析的流程定义:', flowDef);

        if (!flowDef || !Array.isArray(flowDef.steps)) {
          throw new Error('流程定义缺少steps数组');
        }

        // 转换后端步骤格式到前端格式
        const convertedSteps: Api.Compute.Step[] = (flowDef.steps || []).map((backendStep: any, index: number) => {
          // console.log(`转换步骤 ${index}:`, backendStep);

          const step: Api.Compute.Step = {
            name: backendStep.step || backendStep.name || `步骤${index + 1}`,
            type: backendStep.type || 'groovy',
            description: backendStep.description || `${backendStep.step || '步骤'}的描述`,
            script: backendStep.script || backendStep.groovyConfig?.script || '// Groovy脚本\nreturn input',
            mappingConfig: backendStep.mappingConfig || '{}',
            url: backendStep.url || '',
            method: backendStep.method || 'GET',
            headers: backendStep.headers || '{}',
            query: backendStep.sqlConfig?.sql || backendStep.query || '',
            dataSource: backendStep.dataSource || 'default',
            // 添加模型相关字段的处理
            modelId: backendStep.modelId || '',
            parameters: backendStep.modelParameters || backendStep.parameters || '{}',
            // 添加输入输出参数Schema字段的处理
            inputSchema: backendStep.inputSchema || '',
            outputSchema: backendStep.outputSchema || ''
          };

          // console.log(`转换后的步骤 ${index}:`, step);
          return step;
        });

        flowSteps.value = convertedSteps;
        // console.log('最终转换的步骤数组:', convertedSteps);

        // 加载连线信息
        if (flowDef.connections && Array.isArray(flowDef.connections)) {
          flowConnections.value = flowDef.connections;
          // console.log('加载的连线信息:', flowDef.connections);
        } else {
          flowConnections.value = [];
        }

        // 加载节点位置信息
        if (flowDef.nodePositions && typeof flowDef.nodePositions === 'object') {
          nodePositions.value = flowDef.nodePositions;
          // console.log('加载的节点位置信息:', flowDef.nodePositions);
        } else {
          nodePositions.value = {};
        }
      } catch (error) {
        console.error('流程定义解析错误:', error);
        console.error('错误详情:', error instanceof Error ? error.message : '未知错误');
        message.error(`流程定义格式错误: ${error instanceof Error ? error.message : '请检查数据格式'}`);
        flowSteps.value = [];
      }
    } else {
      flowSteps.value = [];
    }
  } catch {
    message.error('加载流程定义失败');
  }
};

const getStepTypeLabel = (type: string) => {
  const labels: Record<string, string> = {
    groovy: 'Groovy脚本',
    mapping: '数据映射',
    rest: 'REST调用',
    sql: 'SQL查询',
    service: 'Service调用',
    model: '模型调用',
    input_param: '输入参数定义',
    output_param: '输出参数定义',
    condition: '条件分支',
    parallel: '并行执行',
    loop: '循环'
  };
  return labels[type] || type;
};

// 修复步骤配置对象
const fixStepConfig = (step: any) => {
  // 参数验证：确保step存在且有type属性
  if (!step || !step.type) {
    console.error('fixStepConfig: step参数无效', step);
    return step || {};
  }

  const fixedStep = { ...step };

  // 确保每种类型的步骤都有正确的配置对象
  switch (step.type) {
    case 'groovy':
      if (!fixedStep.script) fixedStep.script = '// Groovy脚本\nreturn input';
      break;
    case 'mapping':
      if (!fixedStep.mappingConfig) fixedStep.mappingConfig = '{}';
      break;
    case 'rest':
      if (!fixedStep.url) fixedStep.url = '';
      if (!fixedStep.method) fixedStep.method = 'GET';
      if (!fixedStep.headers) fixedStep.headers = '{}';
      break;
    case 'sql':
      if (!fixedStep.query) fixedStep.query = '';
      if (!fixedStep.dataSource) fixedStep.dataSource = 'default';
      break;
    case 'service':
      if (!fixedStep.serviceCode) fixedStep.serviceCode = '';
      if (!fixedStep.methodName) fixedStep.methodName = '';
      break;
    case 'model':
      if (!fixedStep.modelId) fixedStep.modelId = '';
      if (!fixedStep.parameters) fixedStep.parameters = '{}';
      break;
    case 'input_param':
      if (!fixedStep.inputSchema) {
        fixedStep.inputSchema =
          '{\n  "type": "object",\n  "properties": {\n    "example": {\n      "type": "string",\n      "description": "示例参数"\n    }\n  },\n  "required": ["example"]\n}';
      }
      break;
    case 'output_param':
      if (!fixedStep.outputSchema) {
        fixedStep.outputSchema =
          '{\n  "type": "object",\n  "properties": {\n    "result": {\n      "type": "string",\n      "description": "输出结果"\n    }\n  },\n  "required": ["result"]\n}';
      }
      break;
    case 'condition':
      if (!fixedStep.conditionConfig) {
        fixedStep.conditionConfig = {
          condition: 'result != null'
        };
      }
      break;
    case 'parallel':
      if (!fixedStep.parallelConfig) {
        fixedStep.parallelConfig = {
          maxConcurrency: 2
        };
      }
      break;
    case 'loop':
      if (!fixedStep.loopConfig) {
        fixedStep.loopConfig = {
          condition: 'result != null',
          maxIterations: 10
        };
      }
      break;
    default:
      // 其他类型不需要特殊配置
      break;
  }

  return fixedStep;
};

const editStep = (index: number) => {
  // 参数验证：确保index有效且对应的步骤存在
  if (index < 0 || index >= flowSteps.value.length) {
    console.error('editStep: 无效的步骤索引', index, 'flowSteps长度:', flowSteps.value.length);
    return;
  }

  const step = flowSteps.value[index];
  if (!step) {
    console.error('editStep: 步骤不存在', index, step);
    return;
  }

  // 修复步骤配置，确保所有必要的字段都存在
  const fixedStep = fixStepConfig(step);
  currentStep.value = { ...fixedStep };
  editingStepIndex.value = index;

  stepModalVisible.value = true;
};

const saveStep = () => {
  if (editingStepIndex.value >= 0) {
    flowSteps.value[editingStepIndex.value] = { ...currentStep.value };
  } else {
    flowSteps.value.push({ ...currentStep.value });
  }
  stepModalVisible.value = false;
};

const deleteStep = (index: number) => {
  flowSteps.value.splice(index, 1);
  hasUnsavedChanges.value = true;
};

const router = useRouter();

const saveFlow = async () => {
  if (!selectedApiId.value) {
    message.warning('请先选择接口定义');
    return;
  }

  saving.value = true;
  try {
    // 将前端格式转换为后端期望的格式
    const backendSteps = flowSteps.value.map(step => {
      const backendStep = { ...step };

      // 对于模型类型的步骤，将parameters字段映射为modelParameters
      if (step.type === 'model' && step.parameters) {
        backendStep.modelParameters = step.parameters;
        // 删除前端使用的parameters字段，避免混淆
        delete backendStep.parameters;
      }

      return backendStep;
    });

    const flowDefinition = JSON.stringify({
      steps: backendSteps,
      connections: flowConnections.value,
      nodePositions: nodePositions.value
    });

    const api = apiDefinitions.value.find(a => a.id === selectedApiId.value);
    if (!api) {
      message.error('接口定义不存在');
      return;
    }

    await saveApiDefinition({
      ...api,
      flowDefinition
    });

    message.success('流程保存成功');

    // 重置未保存修改状态
    hasUnsavedChanges.value = false;
  } catch {
    message.error('流程保存失败');
  } finally {
    saving.value = false;
  }
};

// 返回接口管理页面
const goBack = () => {
  router.push('/compute/api-management');
};

// 移除了validateFlow函数

// 从API定义中获取输入schema的函数
const getInputSchemaFromFlow = (api: any): string | null => {
  if (!api) return null;

  // 首先检查API定义级别的inputSchema
  if (api.inputSchema) {
    return typeof api.inputSchema === 'string' ? api.inputSchema : JSON.stringify(api.inputSchema);
  }

  // 如果API级别没有inputSchema，则查找流程定义中的input_param步骤
  if (!api.flowDefinition) return null;

  try {
    const flowDef = typeof api.flowDefinition === 'string' ? JSON.parse(api.flowDefinition) : api.flowDefinition;

    // 查找input_param步骤
    const inputStep = flowDef.steps?.find((step: any) => step.type === 'input_param');
    if (inputStep?.inputSchema) {
      const schema = inputStep.inputSchema;
      // 如果是字符串，检查是否为有效JSON
      if (typeof schema === 'string') {
        try {
          // 验证是否为有效JSON
          JSON.parse(schema);
          return schema;
        } catch {
          // 如果不是有效JSON，返回null
          return null;
        }
      } else {
        return JSON.stringify(schema);
      }
    }
    if (inputStep?.schema) {
      const schema = inputStep.schema;
      if (typeof schema === 'string') {
        try {
          JSON.parse(schema);
          return schema;
        } catch {
          return null;
        }
      } else {
        return JSON.stringify(schema);
      }
    }

    return null;
  } catch (error) {
    console.error('解析流程定义失败:', error);
    return null;
  }
};

const generateTestDataFromSchema = (schema: string): any => {
  try {
    const schemaObj = JSON.parse(schema);
    const testData: any = {};

    if (schemaObj.type === 'object' && schemaObj.properties) {
      Object.keys(schemaObj.properties).forEach(key => {
        const property = schemaObj.properties[key];

        switch (property.type) {
          case 'string':
            if (property.enum && property.enum.length > 0) {
              testData[key] = property.enum[0];
            } else {
              testData[key] = property.description ? `示例${property.description}` : 'string_value';
            }
            break;
          case 'number':
          case 'integer':
            testData[key] = 123;
            break;
          case 'boolean':
            testData[key] = true;
            break;
          case 'array':
            if (property.items) {
              if (property.items.type === 'number') {
                testData[key] = [1, 2, 3];
              } else if (property.items.type === 'string') {
                testData[key] = ['item1', 'item2'];
              } else {
                testData[key] = [];
              }
            } else {
              testData[key] = [];
            }
            break;
          case 'object':
            testData[key] = {};
            break;
          default:
            testData[key] = null;
        }
      });
    }

    return testData;
  } catch (error) {
    console.error('解析schema失败:', error);
    return {
      key1: 'value1',
      key2: 123
    };
  }
};

// 从流程图连线中获取开始节点后的第一个步骤
const getFirstStepFromFlowChart = () => {
  if (flowConnections.value.length === 0) {
    // 如果没有连线信息，返回第一个步骤
    return flowSteps.value[0];
  }

  // 查找从开始节点连接的第一个步骤
  const startConnection = flowConnections.value.find(conn => conn.source === 'start');
  if (startConnection) {
    // 从目标节点ID中提取步骤索引
    const targetNodeId = startConnection.target;
    if (targetNodeId.startsWith('step-')) {
      const stepIndex = Number.parseInt(targetNodeId.replace('step-', ''), 10);
      if (!Number.isNaN(stepIndex) && stepIndex >= 0 && stepIndex < flowSteps.value.length) {
        return flowSteps.value[stepIndex];
      }
    }
  }

  // 如果没有找到连接，返回第一个步骤作为默认值
  return flowSteps.value[0];
};

// 转换参数值
const convertParamValue = (type: string, value: string) => {
  switch (type) {
    case 'DOUBLE':
    case 'FLOAT':
      return Number.parseFloat(value);
    case 'INTEGER':
      return Number.parseInt(value, 10);
    case 'BOOLEAN':
      return value === 'true';
    default:
      return value;
  }
};

// 根据类型获取默认值
const getDefaultValueByType = (type: string) => {
  switch (type) {
    case 'DOUBLE':
    case 'FLOAT':
      return 100.0;
    case 'INTEGER':
      return 100;
    case 'BOOLEAN':
      return true;
    default:
      return 'sample_value';
  }
};

// 获取模型输入参数

// 生成Schema测试数据
const generateSchemaTestData = (): Record<string, any> => {
  const api = apiDefinitions.value.find(a => a.id === selectedApiId.value);
  const inputSchema = getInputSchemaFromFlow(api);
  if (api && inputSchema) {
    message.success('已根据接口定义生成测试数据');
    return generateTestDataFromSchema(inputSchema);
  }
  return {};
};

// 获取模型输入参数
const getModelInputParameters = async (model: any) => {
  let inputParams = model.parameters;

  // 如果模型没有参数或参数为空，尝试通过反射API获取
  if (model.id && (!inputParams || inputParams.length === 0)) {
    try {
      const paramResponse = await fetchParametersByModelIdReflection(model.id);
      if (paramResponse.data && paramResponse.data.length > 0) {
        inputParams = paramResponse.data.filter((p: any) => p.direction === 'INPUT');
        // console.log('通过反射API获取到模型参数:', inputParams);
      }
    } catch (error) {
      console.warn('通过反射API获取模型参数失败:', error);
    }
  }

  return inputParams && Array.isArray(inputParams) ? inputParams : [];
};

// 生成模型测试数据
const generateModelTestData = async (firstStep: any): Promise<Record<string, any>> => {
  try {
    const modelsResponse = await listDiscoveredModels();
    const models = (modelsResponse as any)?.data || modelsResponse || [];
    const model = models.find((m: any) => m.code === firstStep.modelId);

    if (!model) {
      console.warn('未找到模型:', firstStep.modelId);
      message.warning(`未找到模型 ${firstStep.modelId}，使用接口Schema生成测试数据`);
      return {};
    }

    const inputParams = await getModelInputParameters(model);
    if (inputParams && inputParams.length > 0) {
      const testData: Record<string, any> = {};
      inputParams.forEach((param: any) => {
        testData[param.name] = param.defaultValue
          ? convertParamValue(param.type, param.defaultValue)
          : getDefaultValueByType(param.type);
      });
      message.success(`已根据模型 ${model.name || firstStep.modelId} 的输入参数自动生成测试数据`);
      return testData;
    }

    console.warn('模型无输入参数定义:', firstStep.modelId);
    message.warning(`模型 ${model.name || firstStep.modelId} 无输入参数定义，使用接口Schema生成测试数据`);
    return {};
  } catch (error) {
    console.error('获取模型参数失败:', error);
    message.warning('获取模型参数失败，使用接口Schema生成测试数据');
    return {};
  }
};

// 生成第一步数据
const generateFirstStepData = async (): Promise<Record<string, any>> => {
  const firstStep = getFirstStepFromFlowChart();

  if (firstStep?.type === 'model' && firstStep.modelId) {
    const modelData = await generateModelTestData(firstStep);
    if (Object.keys(modelData).length > 0) {
      return modelData;
    }
  }

  return generateSchemaTestData();
};

// 生成后续步骤数据
const generateSubsequentStepData = (startStepIndex: number): Record<string, any> => {
  const prevResult = stepTestResults.value[startStepIndex - 1];
  if (prevResult?.success) {
    const inputData = prevResult.currentStepResult?.result || prevResult.result || {};
    // console.log('从步骤', startStepIndex + 1, '开始测试，使用步骤', startStepIndex, '的结果作为输入:', inputData);
    return inputData;
  }

  message.warning(`步骤 ${startStepIndex + 1} 需要先执行前面的步骤，将从第一步开始测试`);
  currentStepIndex.value = 0;
  return generateSchemaTestData();
};

// 生成步骤测试数据
const generateStepTestData = async (startStepIndex: number): Promise<Record<string, any>> => {
  if (startStepIndex === 0) {
    return await generateFirstStepData();
  }
  return generateSubsequentStepData(startStepIndex);
};
// 生成回退测试数据
const generateFallbackTestData = () => {
  if (selectedApiId.value) {
    const api = apiDefinitions.value.find(a => a.id === selectedApiId.value);
    const inputSchema = getInputSchemaFromFlow(api);
    if (api && inputSchema) {
      return generateTestDataFromSchema(inputSchema);
    }
  }
  return { key1: 'value1', key2: 123 };
};

// 从模型生成测试数据
const generateTestDataFromModel = async (modelId: string) => {
  try {
    const modelsResponse = await listDiscoveredModels();
    const models = (modelsResponse as any)?.data || modelsResponse || [];
    // 使用code字段匹配模型，因为步骤中存储的modelId实际上是模型的code
    const model = models.find((m: any) => m.code === modelId);

    if (!model) {
      console.warn('未找到模型:', modelId);
      message.warning(`未找到模型 ${modelId}，使用接口Schema生成测试数据`);
      return generateFallbackTestData();
    }

    if (!model.parameters?.length) {
      console.warn('模型无输入参数定义:', modelId);
      message.warning('模型无输入参数定义，使用接口Schema生成测试数据');
      return generateFallbackTestData();
    }

    const testData: Record<string, any> = {};
    model.parameters.forEach((param: any) => {
      testData[param.name] = param.defaultValue
        ? convertParamValue(param.type, param.defaultValue)
        : getDefaultValueByType(param.type);
    });

    message.success(`已根据模型 ${model.name || modelId} 的输入参数自动生成测试数据`);
    return testData;
  } catch (error) {
    console.error('获取模型参数失败:', error);
    message.warning('获取模型参数失败，使用接口Schema生成测试数据');
    return generateFallbackTestData();
  }
};

// 从输入参数生成测试数据
const generateTestDataFromInputParam = (inputSchema: any) => {
  try {
    const testData = generateTestDataFromSchema(inputSchema);
    message.success('已根据流程图第一个步骤的输入参数定义生成测试数据');
    return testData;
  } catch (error) {
    console.error('根据输入参数定义生成测试数据失败:', error);
    message.warning('根据输入参数定义生成测试数据失败，使用接口Schema生成测试数据');
    return generateFallbackTestData();
  }
};

// 生成测试数据的辅助函数
const generateTestDataFromFirstStep = async () => {
  if (flowSteps.value.length === 0) {
    return {};
  }

  const firstStep = getFirstStepFromFlowChart();

  if (firstStep?.type === 'model' && firstStep.modelId) {
    return await generateTestDataFromModel(firstStep.modelId);
  }

  if (firstStep?.type === 'input_param' && firstStep.inputSchema) {
    return generateTestDataFromInputParam(firstStep.inputSchema);
  }

  return {};
};

const testFlow = async () => {
  testModalVisible.value = true;

  // 生成测试数据
  let testData = await generateTestDataFromFirstStep();

  // 如果没有从第一个步骤生成数据，使用接口Schema生成测试数据
  if (Object.keys(testData).length === 0) {
    testData = generateFallbackTestData();
    const messageText = selectedApiId.value ? '已根据接口定义生成测试数据' : '使用默认测试数据';
    message.info(messageText);
  }

  testInput.value = JSON.stringify(testData, null, 2);
};

const executeTest = async () => {
  if (!selectedApiId.value) {
    message.warning('请先选择接口定义');
    return;
  }

  testing.value = true;
  testResult.value = null;

  try {
    let inputData: any;
    try {
      inputData = JSON.parse(testInput.value);
    } catch {
      message.error('输入数据格式错误');
      testing.value = false;
      return;
    }

    const api = apiDefinitions.value.find(a => a.id === selectedApiId.value);
    if (!api) {
      message.error('接口定义不存在');
      testing.value = false;
      return;
    }

    const computeRequest = {
      bizCode: api.bizCode,
      inputData,
      traceId: `test_${Date.now()}`
    };

    const response = await executeComputeFlow(computeRequest);
    // 现在后端返回ApiResponse<ComputeResponse>，所以response.data是ComputeResponse
    testResult.value = response.data;

    if (response.data?.header?.success) {
      message.success('测试执行成功');
    } else {
      message.warning('测试执行完成，但结果显示失败');
    }
  } catch (error: any) {
    message.error('测试执行失败');
    testResult.value = { error: error.message || '未知错误' };
  } finally {
    testing.value = false;
  }
};

// 移除了showStepTestResult函数，因为不再使用列表视图

const startStepByStepTest = async (startStepIndex = 0) => {
  if (!selectedApiId.value) {
    message.error('请先选择接口定义');
    return;
  }

  if (flowSteps.value.length === 0) {
    message.error('请先添加流程步骤');
    return;
  }

  // 重置逐步测试状态
  currentStepIndex.value = startStepIndex;
  stepByStepResult.value = null;
  stepByStepContext.value = null;

  // 生成测试数据
  const testData = await generateStepTestData(startStepIndex);

  stepByStepInput.value = JSON.stringify(testData, null, 2);
  stepByStepModalVisible.value = true;
};

// openStepByStepTest函数已被整合到startStepByStepTest中

const executeStepByStep = async () => {
  if (!selectedApiId.value) {
    message.error('请先选择接口定义');
    return;
  }

  try {
    stepByStepTesting.value = true;
    testingStepIndex.value = currentStepIndex.value;
    const api = apiDefinitions.value.find(a => a.id === selectedApiId.value);
    if (!api) {
      message.error('接口定义不存在');
      return;
    }

    const inputData = stepByStepInput.value ? JSON.parse(stepByStepInput.value) : {};
    const request = {
      bizCode: api.bizCode,
      traceId: `step_test_${Date.now()}`,
      inputData,
      stepIndex: currentStepIndex.value,
      singleStep: true
    };

    const response = await apiExecuteStepByStep(request);
    // console.log('executeStepByStep response:', response.data);
    stepByStepResult.value = response.data;
    // 修改：使用 context 而不是 currentContext
    stepByStepContext.value = response.data?.context;
    // console.log('After setting stepByStepContext:', stepByStepContext.value);
    // 更新当前步骤索引
    // console.log('更新currentStepIndex，从', currentStepIndex.value, '到', response.data?.currentStepIndex || 0);

    // 修复：executeStepByStep执行完成后，currentStepIndex应该保持为当前执行的步骤索引
    // 这样前端逻辑可以正确判断是否需要调用continueNextStep
    currentStepIndex.value = request.stepIndex;
    // console.log('更新后的currentStepIndex:', currentStepIndex.value);

    // 保存测试结果到步骤测试结果中，以便在流程设计器中显示
    stepTestResults.value[currentStepIndex.value] = {
      ...response.data,
      stepIndex: currentStepIndex.value,
      inputData,
      timestamp: new Date().toLocaleString()
    };

    if (response.data?.completed) {
      message.success('流程执行完成');
    } else {
      message.success(`步骤 ${(response.data?.currentStepIndex ?? 0) + 1} 执行成功`);

      // 修复：不要在这里更新currentStepIndex，保持当前步骤索引不变
      // 这样在continueNextStep中计算nextStepIndex时才是正确的
      // currentStepIndex应该始终表示当前已完成的步骤索引
    }
  } catch (error: any) {
    console.error('测试失败:', error);
    message.error(`测试失败: ${error.message || '未知错误'}`);

    // 保存错误信息到步骤测试结果中
    stepTestResults.value[currentStepIndex.value] = {
      success: false,
      error: error.message || '未知错误',
      stepIndex: currentStepIndex.value,
      timestamp: new Date().toLocaleString()
    };
  } finally {
    stepByStepTesting.value = false;
    testingStepIndex.value = -1;
  }
};

const continueNextStep = async () => {
  if (!stepByStepResult.value || !stepByStepResult.value.traceId) {
    message.error('请先执行第一步');
    return;
  }

  try {
    stepByStepTesting.value = true;
    // 修复bug：确保nextStepIndex是当前步骤索引+1
    const nextStepIndex = currentStepIndex.value + 1;
    // console.log('计算下一步索引:', currentStepIndex.value, ' + 1 =', nextStepIndex);
    testingStepIndex.value = nextStepIndex;

    // 添加日志，查看上下文
    // console.log('stepByStepContext:', stepByStepContext.value);
    // console.log('stepByStepResult:', stepByStepResult.value);

    // 自动使用当前步骤的结果作为下一步的输入数据
    if (currentStepIndex.value >= 0 && stepTestResults.value[currentStepIndex.value]) {
      const prevResult = stepTestResults.value[currentStepIndex.value];
      if (prevResult.success && (prevResult.currentStepResult?.result || prevResult.result)) {
        const inputData = prevResult.currentStepResult?.result || prevResult.result || {};
        stepByStepInput.value = JSON.stringify(inputData, null, 2);
        console.log(
          '自动设置步骤',
          nextStepIndex + 1,
          '的输入数据为步骤',
          currentStepIndex.value + 1,
          '的结果:',
          inputData
        );
      }
    }

    const request = {
      traceId: stepByStepResult.value.traceId,
      context: stepByStepContext.value,
      nextStepIndex,
      singleStep: true
    };

    // console.log('continueStep request:', request);

    const response = await continueStep(request);
    // console.log('continueStep response:', response.data);
    stepByStepResult.value = response.data;
    // console.log('Setting stepByStepContext from:', response.data?.context);
    // 修改：使用 context 而不是 currentContext
    stepByStepContext.value = response.data?.context;
    console.log('After setting stepByStepContext:', stepByStepContext.value);
    // 更新当前步骤索引
    console.log('更新currentStepIndex，从', currentStepIndex.value, '到', response.data?.currentStepIndex || 0);

    // 修复：执行下一步成功后，currentStepIndex应该更新为刚刚执行的步骤索引
    // nextStepIndex就是刚刚执行的步骤索引
    currentStepIndex.value = nextStepIndex;
    console.log('更新后的currentStepIndex:', currentStepIndex.value);

    // 保存测试结果到步骤测试结果中，以便在流程设计器中显示
    stepTestResults.value[currentStepIndex.value] = {
      ...response.data,
      stepIndex: currentStepIndex.value,
      timestamp: new Date().toLocaleString()
    };

    if (response.data?.completed) {
      message.success('流程执行完成');
    } else {
      message.success(`步骤 ${(response.data?.currentStepIndex ?? 0) + 1} 执行成功`);
    }
  } catch (error: any) {
    console.error('继续执行失败:', error);
    message.error(`继续执行失败: ${error.message || '未知错误'}`);

    // 保存错误信息到步骤测试结果中
    // 修复bug：使用当前计算的nextStepIndex而不是从stepByStepResult中获取
    const nextStepIndex = currentStepIndex.value + 1;
    // console.log('错误处理中使用的nextStepIndex:', nextStepIndex);

    // 即使在错误情况下，也更新currentStepIndex到下一步
    // console.log('错误情况下更新currentStepIndex，从', currentStepIndex.value, '到', nextStepIndex);
    currentStepIndex.value = nextStepIndex;
    // console.log('错误情况下更新后的currentStepIndex:', currentStepIndex.value);

    stepTestResults.value[nextStepIndex] = {
      success: false,
      error: error.message || '未知错误',
      stepIndex: nextStepIndex,
      timestamp: new Date().toLocaleString()
    };
  } finally {
    stepByStepTesting.value = false;
    testingStepIndex.value = -1;
  }
};

// testSingleStep函数已被整合到startStepByStepTest中

const clearStepTestResults = () => {
  stepTestResults.value = {};
  message.success('已清除所有测试结果');
};

// 模型相关方法
const loadAvailableModels = async () => {
  try {
    loadingModels.value = true;
    const response = await listDiscoveredModels();
    // transformBackendResponse已经提取了data字段，response.data就是模型数组
    availableModels.value = (response as any)?.data || response || [];
  } catch (error) {
    message.error('加载可用模型失败');
    console.error('加载可用模型失败:', error);
  } finally {
    loadingModels.value = false;
  }
};

const onModelCodeChange = async (value: any) => {
  const modelCode = value as string;
  if (!modelCode) {
    modelParameters.value = [];
    return;
  }

  // 根据modelCode找到对应的模型
  const selectedModel = availableModels.value.find(model => model.code === modelCode);
  if (!selectedModel || !selectedModel.parameters) {
    modelParameters.value = [];
    return;
  }

  // 直接使用模型中的参数数据
  modelParameters.value = selectedModel.parameters || [];
};

// 移除了步骤类型选择相关变量，现在使用拖拽方式

// 根据类型创建步骤
const createStepByType = (type: string): any => {
  const baseStep = {
    name: `${getStepTypeLabel(type)}${flowSteps.value.length + 1}`,
    type: type as
      | 'groovy'
      | 'mapping'
      | 'rest'
      | 'sql'
      | 'model'
      | 'input_param'
      | 'output_param'
      | 'condition'
      | 'parallel'
      | 'loop',
    description: `${getStepTypeLabel(type)}的描述`
  };

  switch (type) {
    case 'groovy':
      return {
        ...baseStep,
        script: '// Groovy脚本\nreturn input'
      };
    case 'mapping':
      return {
        ...baseStep,
        mappingConfig: '{}'
      };
    case 'rest':
      return {
        ...baseStep,
        url: '',
        method: 'GET',
        headers: '{}'
      };
    case 'sql':
      return {
        ...baseStep,
        query: '',
        dataSource: 'default'
      };
    case 'model':
      return {
        ...baseStep,
        modelId: '',
        parameters: '{}'
      };
    case 'input_param':
      return {
        ...baseStep,
        inputSchema:
          '{\n  "type": "object",\n  "properties": {\n    "example": {\n      "type": "string",\n      "description": "示例参数"\n    }\n  },\n  "required": ["example"]\n}'
      };
    case 'output_param':
      return {
        ...baseStep,
        outputSchema:
          '{\n  "type": "object",\n  "properties": {\n    "result": {\n      "type": "string",\n      "description": "输出结果"\n    }\n  },\n  "required": ["result"]\n}'
      };
    case 'condition':
      return {
        ...baseStep,
        conditionConfig: {
          condition: 'result != null'
        }
      };
    case 'parallel':
      return {
        ...baseStep,
        parallelConfig: {
          maxConcurrency: 2
        }
      };
    case 'loop':
      return {
        ...baseStep,
        loopConfig: {
          condition: 'result != null',
          maxIterations: 10
        }
      };
    default:
      return baseStep;
  }
};

// 在流程图中添加步骤
const addStepToChart = (stepType: string, _position?: { x: number; y: number }) => {
  const newStep = createStepByType(stepType);
  flowSteps.value.push(newStep);

  // 清除测试结果
  stepTestResults.value = {};

  // 标记有未保存的修改
  hasUnsavedChanges.value = true;

  message.success(`已添加${getStepTypeLabel(stepType)}步骤到流程图`);
};

// 处理流程图更新事件
const onFlowStepsUpdate = () => {
  hasUnsavedChanges.value = true;
  message.info('流程已修改，请记得保存');
};

// 处理连线更新
const onConnectionsUpdate = (connections: any[]) => {
  flowConnections.value = connections;
  hasUnsavedChanges.value = true;
  message.info('连线已修改，请记得保存');
};

// 处理节点位置更新
const onNodePositionsUpdate = (positions: Record<string, { x: number; y: number }>) => {
  nodePositions.value = positions;
  hasUnsavedChanges.value = true;
};

// 移除了列表视图相关的拖拽处理函数

// 开始拖拽 - 仅用于步骤工具箱
const onDragStart = (event: DragEvent, stepType: string) => {
  if (event.dataTransfer) {
    event.dataTransfer.setData('text/plain', stepType);
    event.dataTransfer.effectAllowed = 'copy';
  }
};

// 生命周期

const route = useRoute();

onMounted(async () => {
  await loadApiDefinitions();
  // 预加载可用服务
  await loadAvailableModels();
  // 从路由query中获取apiId
  const apiId = route.query.apiId as string;
  if (apiId) {
    selectedApiId.value = apiId;
    // 加载对应的接口定义
    loadApiDefinition(apiId);
  }
});

// 页面离开提醒
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
  if (hasUnsavedChanges.value) {
    event.preventDefault();
    event.returnValue = '您有未保存的修改，确定要离开吗？';
    return '您有未保存的修改，确定要离开吗？';
  }
  return undefined;
};

// 添加事件监听器
onMounted(() => {
  window.addEventListener('beforeunload', handleBeforeUnload);
});

// 清理事件监听器
onBeforeUnmount(() => {
  window.removeEventListener('beforeunload', handleBeforeUnload);
});
</script>

<template>
  <div class="flow-designer-container">
    <div class="toolbar">
      <ASpace>
        <AButton type="primary" :loading="saving" @click="saveFlow">
          <template #icon><SaveOutlined /></template>
          保存流程
          <span v-if="hasUnsavedChanges" class="unsaved-indicator">*</span>
        </AButton>
        <AButton @click="goBack">
          <template #icon><ExportOutlined /></template>
          返回
        </AButton>

        <AButton @click="testFlow">
          <template #icon><PlayCircleOutlined /></template>
          测试执行
        </AButton>
        <AButton @click="() => startStepByStepTest(0)">
          <template #icon><PlayCircleOutlined /></template>
          逐步执行
        </AButton>
        <AButton v-if="Object.keys(stepTestResults).length > 0" @click="clearStepTestResults">
          <template #icon><DeleteOutlined /></template>
          清除测试结果
        </AButton>
        <!-- 移除了视图切换按钮，仅保留流程图视图 -->
        <ADivider type="vertical" />
        <ASpace>
          <span>自动连接:</span>
          <ASwitch v-model:checked="autoConnect" size="small" />
        </ASpace>
        <ADivider type="vertical" />
        <div class="api-display">
          <span v-if="selectedApi" class="selected-api-info">{{ selectedApi.name }} ({{ selectedApi.bizCode }})</span>
          <span v-else class="no-api-selected">未选择接口定义</span>
        </div>
      </ASpace>
    </div>

    <div class="designer-content">
      <div class="flow-canvas">
        <div class="canvas-placeholder">
          <h3>流程设计器</h3>
          <p>选择接口定义后开始设计流程</p>

          <!-- 流程图视图 -->
          <div class="flow-chart-container">
            <FlowChart
              :flow-steps="flowSteps"
              :connections="flowConnections"
              :node-positions="nodePositions"
              :auto-connect="autoConnect"
              @step-click="(step, index) => editStep(index)"
              @step-delete="deleteStep"
              @step-add="addStepToChart"
              @update:flow-steps="onFlowStepsUpdate"
              @update:connections="onConnectionsUpdate"
              @update:node-positions="onNodePositionsUpdate"
            />
          </div>
        </div>
      </div>

      <div class="node-panel">
        <div class="panel-header">
          <h3>步骤工具箱</h3>
        </div>

        <div class="node-types">
          <!-- 输入报文步骤已移除 -->

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'groovy')">
            <CodeOutlined />
            <span>Groovy脚本</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'mapping')">
            <SwapOutlined />
            <span>数据映射</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'rest')">
            <ApiOutlined />
            <span>REST调用</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'sql')">
            <DatabaseOutlined />
            <span>SQL查询</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'service')">
            <ApiOutlined />
            <span>Service调用</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'model')">
            <SettingOutlined />
            <span>模型调用</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'input_param')">
            <ImportOutlined />
            <span>输入参数定义</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'output_param')">
            <ExportOutlined />
            <span>输出参数定义</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'condition')">
            <BranchesOutlined />
            <span>条件分支</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'parallel')">
            <SyncOutlined />
            <span>并行执行</span>
          </div>

          <div class="node-type" draggable="true" @dragstart="onDragStart($event, 'loop')">
            <ReloadOutlined />
            <span>循环</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 步骤编辑对话框 -->
    <AModal
      v-model:open="stepModalVisible"
      :title="editingStepIndex >= 0 ? '编辑步骤' : '新增步骤'"
      width="1200px"
      @ok="saveStep"
    >
      <AForm :model="currentStep" layout="vertical">
        <!-- 基本信息行 -->
        <ARow :gutter="16">
          <ACol :span="8">
            <AFormItem label="步骤名称">
              <AInput v-model:value="currentStep.name" placeholder="请输入步骤名称" />
            </AFormItem>
          </ACol>
          <ACol :span="6">
            <AFormItem label="步骤类型">
              <ASelect v-model:value="currentStep.type" disabled>
                <ASelectOption value="input">输入报文</ASelectOption>
                <ASelectOption value="groovy">Groovy脚本</ASelectOption>
                <ASelectOption value="mapping">数据映射</ASelectOption>
                <ASelectOption value="rest">REST调用</ASelectOption>
                <ASelectOption value="sql">SQL查询</ASelectOption>
                <ASelectOption value="model">模型调用</ASelectOption>
                <ASelectOption value="input_param">输入参数定义</ASelectOption>
                <ASelectOption value="output_param">输出参数定义</ASelectOption>
              </ASelect>
            </AFormItem>
          </ACol>
          <ACol :span="10">
            <AFormItem label="描述">
              <AInput v-model:value="currentStep.description" placeholder="请输入步骤描述" />
            </AFormItem>
          </ACol>
        </ARow>

        <!-- 输入报文配置已移除 -->

        <!-- Groovy脚本配置 -->
        <template v-if="currentStep.type === 'groovy'">
          <AFormItem label="Groovy脚本">
            <CodeEditor
              v-model="currentStep.script"
              language="groovy"
              :height="400"
              placeholder="请输入Groovy脚本"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- 数据映射配置 -->
        <template v-if="currentStep.type === 'mapping'">
          <AFormItem label="映射配置">
            <CodeEditor
              v-model="currentStep.mappingConfig"
              language="json"
              :height="300"
              placeholder="请输入JSON格式的映射配置"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- REST调用配置 -->
        <template v-if="currentStep.type === 'rest'">
          <ARow :gutter="16">
            <ACol :span="18">
              <AFormItem label="请求URL">
                <AInput v-model:value="currentStep.url" placeholder="请输入请求URL" />
              </AFormItem>
            </ACol>
            <ACol :span="6">
              <AFormItem label="请求方法">
                <ASelect v-model:value="currentStep.method">
                  <ASelectOption value="GET">GET</ASelectOption>
                  <ASelectOption value="POST">POST</ASelectOption>
                  <ASelectOption value="PUT">PUT</ASelectOption>
                  <ASelectOption value="DELETE">DELETE</ASelectOption>
                </ASelect>
              </AFormItem>
            </ACol>
          </ARow>
          <AFormItem label="请求头">
            <CodeEditor
              v-model="currentStep.headers"
              language="json"
              :height="200"
              placeholder="请输入JSON格式的请求头"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- SQL查询配置 -->
        <template v-if="currentStep.type === 'sql'">
          <AFormItem label="数据源">
            <AInput v-model:value="currentStep.dataSource" placeholder="请输入数据源名称" style="width: 300px" />
          </AFormItem>
          <AFormItem label="SQL查询">
            <CodeEditor
              v-model="currentStep.query"
              language="sql"
              :height="300"
              placeholder="请输入SQL查询语句"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- 模型调用配置 -->
        <template v-if="currentStep.type === 'model'">
          <ARow :gutter="16">
            <ACol :span="24">
              <AFormItem label="模型选择">
                <ASelect
                  v-model:value="currentStep.modelId"
                  placeholder="请选择模型"
                  show-search
                  :filter-option="false"
                  :loading="loadingModels"
                  @focus="loadAvailableModels"
                  @change="onModelCodeChange"
                >
                  <ASelectOption v-for="model in availableModels" :key="model.code" :value="model.code">
                    {{ model.code }} - {{ model.name }}
                  </ASelectOption>
                </ASelect>
              </AFormItem>
            </ACol>
          </ARow>
          <AFormItem label="模型参数配置">
            <CodeEditor
              v-model="currentStep.parameters"
              language="json"
              :height="200"
              placeholder="请输入JSON格式的模型参数配置"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- Service调用配置 -->
        <template v-if="currentStep.type === 'service'">
          <AFormItem label="Service编码">
            <AInput v-model:value="currentStep.serviceCode" placeholder="请输入Service编码" />
          </AFormItem>
          <AFormItem label="方法名称">
            <AInput v-model:value="currentStep.methodName" placeholder="请输入方法名称" />
          </AFormItem>
        </template>

        <!-- 输入参数定义配置 -->
        <template v-if="currentStep.type === 'input_param'">
          <AFormItem label="输入参数Schema定义">
            <CodeEditor
              v-model="currentStep.inputSchema"
              language="json"
              :height="400"
              placeholder="请输入JSON Schema格式的输入参数定义"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- 输出参数定义配置 -->
        <template v-if="currentStep.type === 'output_param'">
          <AFormItem label="输出参数Schema定义">
            <CodeEditor
              v-model="currentStep.outputSchema"
              language="json"
              :height="400"
              placeholder="请输入JSON Schema格式的输出参数定义"
              :auto-format-on-mount="true"
            />
          </AFormItem>
        </template>

        <!-- 条件分支配置 -->
        <template v-if="currentStep.type === 'condition' && currentStep.conditionConfig">
          <AFormItem label="条件表达式">
            <AInput
              v-model:value="currentStep.conditionConfig.condition"
              placeholder="请输入条件表达式，如：result != null"
            />
          </AFormItem>
          <AAlert
            message="执行路径配置"
            description="条件分支的执行路径通过流程图中的连线来配置。条件为真时，执行流程会沿着'是'分支继续；条件为假时，执行流程会沿着'否'分支继续。请在流程图中连接相应的步骤节点。"
            type="info"
            show-icon
            style="margin-bottom: 16px"
          />
        </template>

        <!-- 并行执行配置 -->
        <template v-if="currentStep.type === 'parallel' && currentStep.parallelConfig">
          <AFormItem label="最大并发数">
            <AInputNumber
              v-model:value="currentStep.parallelConfig.maxConcurrency"
              :min="1"
              :max="10"
              placeholder="请输入最大并发数"
            />
          </AFormItem>
          <AAlert
            message="并行分支配置"
            description="并行执行的分支路径通过流程图中的连线来配置。每个并行分支会从当前节点的不同输出点连接到相应的步骤节点，实现并行执行。"
            type="info"
            show-icon
            style="margin-bottom: 16px"
          />
        </template>

        <!-- 循环配置 -->
        <template v-if="currentStep.type === 'loop' && currentStep.loopConfig">
          <AFormItem label="循环条件">
            <AInput
              v-model:value="currentStep.loopConfig.condition"
              placeholder="请输入循环条件表达式，如：result != null"
            />
          </AFormItem>
          <AFormItem label="最大迭代次数">
            <AInputNumber
              v-model:value="currentStep.loopConfig.maxIterations"
              :min="1"
              :max="1000"
              placeholder="请输入最大迭代次数"
            />
          </AFormItem>
          <AAlert
            message="循环体配置"
            description="循环体的执行路径通过流程图中的连线来配置。循环节点有两个输出点：'继续'连接到循环体步骤，'回环'连接回循环开始处，实现循环执行。"
            type="info"
            show-icon
            style="margin-bottom: 16px"
          />
        </template>
      </AForm>
    </AModal>

    <!-- 测试执行对话框 -->
    <AModal
      v-model:open="testModalVisible"
      title="测试流程执行"
      width="800px"
      :confirm-loading="testing"
      :destroy-on-close="false"
      @ok="executeTest"
    >
      <div class="test-panel">
        <div class="test-input">
          <div class="input-header">
            <h4>输入数据</h4>
            <AButton
              size="small"
              type="link"
              @click="
                () => {
                  if (selectedApiId) {
                    const api = apiDefinitions.find(a => a.id === selectedApiId);
                    const inputSchema = getInputSchemaFromFlow(api);
                    if (api && inputSchema) {
                      const generatedData = generateTestDataFromSchema(inputSchema);
                      testInput = JSON.stringify(generatedData, null, 2);
                      message.success('已根据接口定义生成测试数据');
                    } else {
                      message.warning('当前接口没有定义输入参数结构');
                    }
                  } else {
                    message.warning('请先选择接口定义');
                  }
                }
              "
            >
              🔄 根据接口定义生成
            </AButton>
          </div>
          <CodeEditor
            v-model="testInput"
            language="json"
            :height="200"
            placeholder="请输入JSON格式的测试数据"
            :auto-format-on-mount="true"
          />
        </div>

        <div v-if="testResult" class="test-result">
          <h4>执行结果</h4>
          <div v-if="(testResult as any).header" class="result-status">
            <div class="status-badge" :class="[(testResult as any).header.success ? 'success' : 'error']">
              {{ (testResult as any).header.success ? '✅ 执行成功' : '❌ 执行失败' }}
            </div>
            <div v-if="(testResult as any).header.message" class="status-message">
              {{ (testResult as any).header.message }}
            </div>
          </div>
          <div v-else-if="(testResult as any).error" class="result-status">
            <div class="status-badge error">❌ 执行失败</div>
            <div class="status-message">{{ (testResult as any).error }}</div>
          </div>
          <pre class="result-data">{{ JSON.stringify(testResult, null, 2) }}</pre>
        </div>
      </div>
    </AModal>

    <!-- 测试流程对话框 -->
    <AModal
      v-model:open="stepByStepModalVisible"
      :title="`测试流程 - 当前步骤: ${currentStepIndex + 1}/${flowSteps.length} (步骤索引: ${currentStepIndex})`"
      width="900px"
      :confirm-loading="stepByStepTesting"
      :destroy-on-close="false"
      :footer="null"
    >
      <div class="step-by-step-panel">
        <div class="step-info">
          <AAlert
            :message="`当前执行步骤: ${currentStepIndex + 1}，步骤索引: ${currentStepIndex}，总步骤数: ${flowSteps.length}`"
            type="info"
            show-icon
          />

          <!-- 分支步骤特殊说明 -->
          <div
            v-if="
              flowSteps[currentStepIndex] &&
              ['condition', 'parallel', 'loop'].includes(flowSteps[currentStepIndex].type)
            "
            class="branch-step-notice"
          >
            <AAlert
              v-if="flowSteps[currentStepIndex].type === 'condition'"
              message="条件分支步骤"
              description="此步骤将根据条件表达式的结果选择执行真分支或假分支中的步骤。测试时会显示条件判断结果和选择的分支路径。"
              type="warning"
              show-icon
              style="margin-top: 8px"
            />
            <AAlert
              v-else-if="flowSteps[currentStepIndex].type === 'parallel'"
              message="并行执行步骤"
              description="此步骤将并行执行多个分支中的步骤。测试时会显示各分支的执行结果和汇总信息。"
              type="warning"
              show-icon
              style="margin-top: 8px"
            />
            <AAlert
              v-else-if="flowSteps[currentStepIndex].type === 'loop'"
              message="循环步骤"
              description="此步骤将重复执行循环体中的步骤，直到条件不满足或达到最大迭代次数。测试时会显示循环执行的详细信息。"
              type="warning"
              show-icon
              style="margin-top: 8px"
            />
          </div>
        </div>
        <div v-if="stepByStepResult" class="step-debug-info">
          <AAlert
            :message="`后端返回信息 - currentStepIndex: ${stepByStepResult.currentStepIndex}，totalSteps: ${stepByStepResult.totalSteps}，completed: ${stepByStepResult.completed}`"
            type="warning"
            show-icon
          />
        </div>
        <div class="step-progress">
          <h4>执行进度</h4>
          <ASteps :current="currentStepIndex" size="small">
            <AStep
              v-for="(step, index) in flowSteps"
              :key="index"
              :title="step.name"
              :description="getStepTypeLabel(step.type)"
            />
          </ASteps>
        </div>

        <div class="step-input">
          <div class="input-header">
            <h4>输入数据</h4>
            <AButton
              size="small"
              type="link"
              @click="
                () => {
                  if (selectedApiId) {
                    const api = apiDefinitions.find(a => a.id === selectedApiId);
                    const inputSchema = getInputSchemaFromFlow(api);
                    if (api && inputSchema) {
                      const generatedData = generateTestDataFromSchema(inputSchema);
                      stepByStepInput = JSON.stringify(generatedData, null, 2);
                      message.success('已根据接口定义生成测试数据');
                    } else {
                      message.warning('当前接口没有定义输入参数结构');
                    }
                  } else {
                    message.warning('请先选择接口定义');
                  }
                }
              "
            >
              🔄 根据接口定义生成
            </AButton>
          </div>
          <CodeEditor
            v-model="stepByStepInput"
            language="json"
            :height="150"
            placeholder="请输入JSON格式的测试数据"
            :auto-format-on-mount="true"
          />
        </div>

        <div class="step-controls">
          <ASpace>
            <AButton
              type="primary"
              :loading="stepByStepTesting"
              :disabled="
                stepByStepTesting ||
                (stepByStepResult && stepByStepResult.completed) ||
                (currentStepIndex >= flowSteps.length - 1 && stepByStepResult) ||
                (stepByStepResult && !stepByStepResult.success)
              "
              @click="!stepByStepResult ? executeStepByStep() : continueNextStep()"
            >
              {{
                !stepByStepResult
                  ? '开始执行第1步'
                  : stepByStepResult.completed
                    ? '流程已完成'
                    : `执行下一步 (步骤${currentStepIndex + 1} → 步骤${currentStepIndex + 2})`
              }}
            </AButton>
            <AButton
              @click="
                () => {
                  currentStepIndex = 0;
                  stepByStepResult = null;
                  stepByStepContext = null;
                }
              "
            >
              重置
            </AButton>
            <AButton @click="stepByStepModalVisible = false">关闭</AButton>
          </ASpace>
        </div>

        <div v-if="stepByStepResult" class="step-result">
          <h4>当前步骤执行结果</h4>
          <div class="result-status">
            <div class="status-badge" :class="[stepByStepResult.success ? 'success' : 'error']">
              {{ stepByStepResult.success ? '✅ 执行成功' : '❌ 执行失败' }}
            </div>
            <div v-if="stepByStepResult.message" class="status-message">
              {{ stepByStepResult.message }}
            </div>
          </div>
        </div>
      </div>
    </AModal>

    <!-- 步骤测试结果展示对话框 -->
    <AModal
      v-model:open="stepTestResultModalVisible"
      :title="`步骤 ${currentViewingStepIndex + 1} 测试结果 - ${flowSteps[currentViewingStepIndex]?.name || ''}`"
      width="800px"
      :footer="null"
      :destroy-on-close="false"
    >
      <div v-if="currentViewingStepResult" class="step-test-result-detail">
        <div class="result-status-header">
          <div class="status-badge-large" :class="[currentViewingStepResult.success ? 'success' : 'error']">
            <span class="status-icon">{{ currentViewingStepResult.success ? '✅' : '❌' }}</span>
            <span class="status-text">{{ currentViewingStepResult.success ? '成功' : '失败' }}</span>
          </div>
          <div v-if="currentViewingStepResult.message" class="status-message-large">
            {{ currentViewingStepResult.message }}
          </div>
        </div>

        <ATabs default-active-key="result" class="result-tabs">
          <ATabPane v-if="currentViewingStepResult.currentStepResult" key="result" tab="当前步骤结果">
            <!-- 分支步骤特殊结果显示 -->
            <div
              v-if="
                flowSteps[currentViewingStepIndex] &&
                ['condition', 'parallel', 'loop'].includes(flowSteps[currentViewingStepIndex].type)
              "
              class="branch-result-summary"
            >
              <div v-if="flowSteps[currentViewingStepIndex].type === 'condition'" class="condition-result">
                <AAlert
                  :message="`条件判断结果: ${currentViewingStepResult.currentStepResult?.conditionResult ? '条件为真' : '条件为假'}`"
                  :description="`执行分支: ${currentViewingStepResult.currentStepResult?.executedBranch || '未知'}`"
                  type="info"
                  show-icon
                  style="margin-bottom: 12px"
                />
              </div>
              <div v-else-if="flowSteps[currentViewingStepIndex].type === 'parallel'" class="parallel-result">
                <AAlert
                  :message="`并行执行完成，共 ${currentViewingStepResult.currentStepResult?.branchResults?.length || 0} 个分支`"
                  :description="`成功: ${(currentViewingStepResult.currentStepResult?.branchResults || []).filter((r: any) => r.success).length} 个，失败: ${(currentViewingStepResult.currentStepResult?.branchResults || []).filter((r: any) => !r.success).length} 个`"
                  type="info"
                  show-icon
                  style="margin-bottom: 12px"
                />
              </div>
              <div v-else-if="flowSteps[currentViewingStepIndex].type === 'loop'" class="loop-result">
                <AAlert
                  :message="`循环执行完成，共执行 ${currentViewingStepResult.currentStepResult?.iterations || 0} 次迭代`"
                  :description="`循环条件: ${currentViewingStepResult.currentStepResult?.finalCondition ? '最终为真' : '最终为假'}`"
                  type="info"
                  show-icon
                  style="margin-bottom: 12px"
                />
              </div>
            </div>

            <CodeEditor
              :model-value="JSON.stringify(currentViewingStepResult.currentStepResult, null, 2)"
              language="json"
              :height="350"
              :read-only="true"
            />
          </ATabPane>

          <ATabPane v-if="currentViewingStepResult.context" key="context" tab="执行上下文">
            <CodeEditor
              :model-value="JSON.stringify(currentViewingStepResult.context, null, 2)"
              language="json"
              :height="350"
              :read-only="true"
            />
          </ATabPane>

          <ATabPane key="full" tab="完整响应数据">
            <CodeEditor
              :model-value="JSON.stringify(currentViewingStepResult, null, 2)"
              language="json"
              :height="350"
              :read-only="true"
            />
          </ATabPane>
        </ATabs>
      </div>
    </AModal>

    <!-- 移除了步骤类型选择对话框，现在使用拖拽方式添加步骤 -->
  </div>
</template>

<style scoped>
.flow-designer-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.step-info,
.step-debug-info {
  margin-bottom: 16px;
}

.toolbar {
  padding: 16px;
  border-bottom: 1px solid #f0f0f0;
  /* background: #fff; */
  display: flex;
  justify-content: space-between;
  align-items: right;
}

.designer-content {
  flex: 1;
  display: flex;
}

.flow-canvas {
  flex: 1;
  position: relative;
  /* background: #fafafa; */
}

.canvas-placeholder {
  padding: 40px;
  text-align: center;
  color: #666;
}

/* 移除了列表视图相关的CSS样式 */

.node-type {
  user-select: none;
}

.flow-step {
  /* background: #fff; */
  /* border: 1px solid #e8e8e8; */
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.flow-step:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  transform: translateY(-2px);
  border-color: #1890ff;
}

.flow-step::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 4px;
  height: 100%;
  background: linear-gradient(135deg, #1890ff, #40a9ff);
}

.step-header .ant-space .ant-btn {
  border-radius: 6px;
  font-size: 12px;
  height: 28px;
  padding: 0 12px;
  font-weight: 500;
  transition: all 0.3s;
}

.step-header .ant-btn:not(.ant-btn-dangerous):hover {
  border-color: #1890ff;
  color: #1890ff;
  /* background: #f0f8ff; */
}

.step-header .ant-btn-dangerous:hover {
  /* background: #fff2f0; */
  border-color: #ff7875;
}

.api-select {
  width: 300px;
}

.step-test-result {
  margin-top: 12px;
  padding: 12px;
  /* background: #f8f9fa; */
  border-radius: 6px;
  border-left: 4px solid #1890ff;
}

.result-status {
  margin-bottom: 8px;
}

.status-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}

.status-badge.success {
  /* background: #f6ffed; */
  color: #52c41a;
  border: 1px solid #b7eb8f;
}

.status-badge.error {
  /* background: #fff2f0; */
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}

/* 新的测试结果指示器样式 */
.step-test-indicator {
  margin-top: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  /* background: #f8f9fa; */
  border-radius: 6px;
  border-left: 4px solid #1890ff;
}

.test-status-badge {
  font-size: 12px;
}

.view-result-btn {
  padding: 0 8px;
  height: 24px;
  font-size: 12px;
}

/* 测试结果详情模态框样式 */
.step-test-result-detail {
  padding: 8px 0;
}

.result-sections {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.result-section {
  border: 1px solid #e8e8e8;
  border-radius: 8px;
}

/* 流程图容器样式 */
.flow-chart-container {
  width: 100%;
  height: 600px;
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  /* background: #fafafa; */
  position: relative;
  overflow: hidden;
}

.result-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  /* background: #fafafa; */
  border-bottom: 1px solid #e8e8e8;
}

.result-section-header h4 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: #333;
}

.status-badge-compact {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}

.status-badge-compact.success {
  /* background: #f6ffed; */
  color: #52c41a;
  border: 1px solid #b7eb8f;
}

.status-badge-compact.error {
  /* background: #fff2f0; */
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}

.status-badge-compact .status-icon {
  font-size: 14px;
}

.status-badge-compact .status-text {
  font-size: 12px;
}

.status-message-compact {
  color: #666;
  font-size: 12px;
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.status-message {
  margin-top: 4px;
  font-size: 12px;
  color: #666;
}

.result-details {
  margin-top: 8px;
}

.result-details summary {
  cursor: pointer;
  font-size: 12px;
  color: #1890ff;
  user-select: none;
}

.result-details summary:hover {
  color: #40a9ff;
}

.result-data {
  margin: 8px 0 0 0;
  padding: 8px;
  /* background: #fff; */
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  font-size: 11px;
  max-height: 200px;
  overflow-y: auto;
}

.step-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #f0f0f0;
}

.step-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.step-type {
  background: linear-gradient(135deg, #1890ff, #40a9ff);
  color: #fff;
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  box-shadow: 0 2px 4px rgba(24, 144, 255, 0.3);
}

.step-index {
  color: #666;
  font-size: 13px;
  font-weight: 500;
}

.drag-handle {
  color: #bfbfbf;
  cursor: grab;
  transition: color 0.3s;
}

.drag-handle:hover {
  color: #1890ff;
}

.step-content {
  padding-left: 4px;
}

.step-content p {
  margin: 6px 0;
  font-size: 14px;
  line-height: 1.5;
}

.step-content strong {
  color: #262626;
  font-weight: 600;
}

.node-panel {
  width: 300px;
  border-left: 1px solid #f0f0f0;
  /* background: #fafafa; */
  display: flex;
  flex-direction: column;
}

.panel-header {
  padding: 16px;
  border-bottom: 1px solid #f0f0f0;
  /* background: #fff; */
}

.panel-header h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
}

.node-types {
  padding: 16px;
}

.node-type {
  display: flex;
  align-items: center;
  padding: 12px;
  margin-bottom: 8px;
  /* background: #fff; */
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
}

.node-type:hover {
  border-color: #1890ff;
  box-shadow: 0 2px 4px rgba(24, 144, 255, 0.2);
}

.node-type .anticon {
  margin-right: 8px;
  font-size: 16px;
  color: #1890ff;
}

.test-panel {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.input-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.input-header h4 {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
}

.test-result h4 {
  margin: 0 0 8px 0;
  font-size: 14px;
  font-weight: 500;
}

.result-status {
  margin-bottom: 16px;
  padding: 12px;
  border-radius: 6px;
  /* background: #f8f9fa; */
}

.status-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 4px;
  font-weight: 500;
  margin-bottom: 8px;
}

.status-badge.success {
  /* background: #f6ffed; */
  color: #52c41a;
  border: 1px solid #b7eb8f;
}

.status-badge.error {
  /* background: #fff2f0; */
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}

.status-message {
  color: #666;
  font-size: 14px;
  line-height: 1.5;
}

.result-data {
  /* background: #f5f5f5; */
  padding: 12px;
  border-radius: 4px;
  max-height: 300px;
  overflow: auto;
  font-size: 12px;
  margin-top: 12px;
}

.step-by-step-panel {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.step-progress h4 {
  margin: 0 0 12px 0;
  font-size: 14px;
  font-weight: 500;
}

.step-input {
  display: flex;
  flex-direction: column;
}

.step-controls {
  display: flex;
  justify-content: center;
  padding: 16px 0;
  border-top: 1px solid #f0f0f0;
  border-bottom: 1px solid #f0f0f0;
}

.step-result {
  margin-top: 16px;
}

.step-result h4 {
  margin: 0 0 12px 0;
  font-size: 14px;
  font-weight: 500;
}

/* 测试结果详情样式 */
.step-test-result-detail {
  padding: 16px 0;
}

.result-status-header {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  /* background-color: #fafafa; */
  border-radius: 6px;
  margin-bottom: 16px;
}

.status-badge-large {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  width: fit-content;
}

.status-badge-large.success {
  /* background-color: #f6ffed; */
  color: #52c41a;
  border: 1px solid #b7eb8f;
}

.status-badge-large.error {
  /* background-color: #fff2f0; */
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}

.status-icon {
  font-size: 14px;
}

.status-text {
  font-size: 14px;
}

.status-message-large {
  font-size: 13px;
  color: #ff4d4f;
  font-weight: 500;
  padding: 8px 12px;
  /* background-color: #fff2f0; */
  border: 1px solid #ffccc7;
  border-radius: 4px;
}

.result-tabs {
  margin-top: 8px;
}

.result-tabs .ant-tabs-content-holder {
  padding: 16px 0;
}

.result-tabs .ant-tabs-tab {
  font-weight: 500;
}

/* API显示样式 */
.api-display {
  padding: 8px 12px;
  /* background: #f5f5f5; */
  border: 1px solid #d9d9d9;
  border-radius: 6px;
  min-width: 200px;
}

.selected-api-info {
  color: #1890ff;
  font-weight: 500;
  font-size: 14px;
}

.no-api-selected {
  color: #999;
  font-style: italic;
  font-size: 14px;
}

/* 修复当前页面按钮图标和文字对齐 */
.flow-designer-container .ant-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.flow-designer-container .ant-btn .anticon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  margin-right: 0px; /* 调整图标与文字之间的距离 */
}

/* 移除了分支、并行、循环可视化相关的CSS样式 */

/* 未保存修改提示样式 */
.unsaved-indicator {
  color: #ff4d4f;
  font-weight: bold;
  margin-left: 4px;
}
</style>
